package com.jsb.wx.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;

import javax.net.ssl.SSLContext;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jsb.common.config.Const;

public class PayCommonUtil {
	public static final String PAYSUCCESS_STATUS = "0";
	public static final String PAYPENDING_STATUS = "1";
	public static final String NETWORK_ERROR_CODE = "2";   //网络错误
	public static final String PENDING_QUERY_CODE = "3";   //发生网络错误，支付结果待查询
	public static final String PAY_ERROR_CODE = "4";   //微信回调异常
	public static final String ALREADY_REFUND_CODE = "5";   //已退回余额
	public static final String PAY_DISAGREE_CODE = "6";   //提现审核不通过
	public static final String PAY_ERRORNAME_CODE = "7";   //实名不一致
	/**
	 * 成功/失败
	 */
	public static final String FAIL_CODE = "0";
	public static final String SUCCESS_CODE = "1";
	
	/**
	 * 成功/失败
	 */
	public static final String SUCCESS = "SUCCESS";
	public static final String FAIL = "FAIL";
    //微信参数配置  
    public static String API_KEY="ihfeSFKFKdsdswlcjdf73jsdxfngzmvb";  
    public static String API_PAYSERVER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    public static String API_QUERYSERVER = "https://api.mch.weixin.qq.com/pay/orderquery";
    
    //企业向个人转账微信API路径
    public static final String ENTERPRISE_PAY_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
    //查询企业付款订单
    public static final String ENTERPRISE_ORDER_URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
    //apiclient_cert.p12证书存放路径
//    public static final String CERTIFICATE_LOCATION = "/data/cert/apiclient_cert.p12";
    public static final String CERTIFICATE_LOCATION = "/cert/apiclient_cert.p12";
    
    //APP
    public static String APPID="wx72ef6980bae5da5c";  
    public static String APPSECRET="6c0e62aa5eeef7b91ee124dc7ea7a8b2";  
    public static String MCH_ID="1361440702";  
    //随机字符串生成  
    public static String getRandomString(int length) { //length表示生成字符串的长度      
           String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";         
           Random random = new Random();         
           StringBuffer sb = new StringBuffer();         
           for (int i = 0; i < length; i++) {         
               int number = random.nextInt(base.length());         
               sb.append(base.charAt(number));         
           }         
           return sb.toString();         
        }    
    //请求xml组装  
      @SuppressWarnings("rawtypes")
	public static String getRequestXml(SortedMap<String,Object> parameters){  
            StringBuffer sb = new StringBuffer();  
            sb.append("<xml>");  
            Set es = parameters.entrySet();  
            Iterator it = es.iterator();  
            while(it.hasNext()) {  
                Map.Entry entry = (Map.Entry)it.next();  
                String key = (String)entry.getKey();  
                String value = (String)entry.getValue();  
                if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {  
                    sb.append("<"+key+">"+"<![CDATA["+value+"]]></"+key+">");  
                }else {  
                    sb.append("<"+key+">"+value+"</"+key+">");  
                }  
            }  
            sb.append("</xml>");  
            return sb.toString();  
        }  
      //生成签名  
      @SuppressWarnings("rawtypes")
	public static String createSign(String characterEncoding,SortedMap<String,Object> parameters){  
            StringBuffer sb = new StringBuffer();  
            Set es = parameters.entrySet();  
            Iterator it = es.iterator();  
            while(it.hasNext()) {  
                Map.Entry entry = (Map.Entry)it.next();  
                String k = (String)entry.getKey();  
                Object v = entry.getValue();  
                if(null != v && !"".equals(v)  
                        && !"sign".equals(k) && !"key".equals(k)) {  
                    sb.append(k + "=" + v + "&");  
                }  
            }  
            sb.append("key=" + API_KEY);  
            System.out.println(sb.toString());
            String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
            return sign;  
        }  
      //请求方法  
      public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {  
            try {  
                 
                URL url = new URL(requestUrl);  
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
                
                conn.setDoOutput(true);  
                conn.setDoInput(true);  
                conn.setUseCaches(false);  
                // 设置请求方式（GET/POST）  
                conn.setRequestMethod(requestMethod);  
                conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");  
                // 当outputStr不为null时向输出流写数据  
                if (null != outputStr) {  
                    OutputStream outputStream = conn.getOutputStream();  
                    // 注意编码格式  
                    outputStream.write(outputStr.getBytes("UTF-8"));  
                    outputStream.close();  
                }  
                // 从输入流读取返回内容  
                InputStream inputStream = conn.getInputStream();  
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
                String str = null;  
                StringBuffer buffer = new StringBuffer();  
                while ((str = bufferedReader.readLine()) != null) {  
                    buffer.append(str);  
                }  
                // 释放资源  
                bufferedReader.close();  
                inputStreamReader.close();  
                inputStream.close();  
                inputStream = null;  
                conn.disconnect();  
                return buffer.toString();  
            } catch (ConnectException ce) {  
                System.out.println("连接超时：{}"+ ce);  
            } catch (Exception e) {  
                System.out.println("https请求异常：{}"+ e);  
            }  
            return null;  
        }  
      //退款的请求方法  
      @SuppressWarnings("deprecation")
	public static String httpsRequest2(String requestUrl, String requestMethod, String outputStr) throws Exception {  
            KeyStore keyStore  = KeyStore.getInstance("PKCS12");  
            StringBuilder res = new StringBuilder("");  
            FileInputStream instream = new FileInputStream(new File("D:/data/cert/apiclient_cert.p12"));  
            try {  
                keyStore.load(instream, "".toCharArray());  
            } finally {  
                instream.close();  
            }  
  
            // Trust own CA and all self-signed certs  
            SSLContext sslcontext = SSLContexts.custom()  
                    .loadKeyMaterial(keyStore, PayCommonUtil.MCH_ID.toCharArray())  
                    .build();  
            // Allow TLSv1 protocol only  
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(  
                    sslcontext,  
                    new String[] { "TLSv1" },  
                    null,  
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
            CloseableHttpClient httpclient = HttpClients.custom()  
                    .setSSLSocketFactory(sslsf)  
                    .build();  
            try {  
  
                HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");  
                httpost.addHeader("Connection", "keep-alive");  
                httpost.addHeader("Accept", "*/*");  
                httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");  
                httpost.addHeader("Host", "api.mch.weixin.qq.com");  
                httpost.addHeader("X-Requested-With", "XMLHttpRequest");  
                httpost.addHeader("Cache-Control", "max-age=0");  
                httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");  
                 StringEntity entity2 = new StringEntity(outputStr ,Consts.UTF_8);  
                 httpost.setEntity(entity2);  
                System.out.println("executing request" + httpost.getRequestLine());  
  
                CloseableHttpResponse response = httpclient.execute(httpost);  
                 
                try {  
                    HttpEntity entity = response.getEntity();  
                      
                    System.out.println("----------------------------------------");  
                    System.out.println(response.getStatusLine());  
                    if (entity != null) {  
                        System.out.println("Response content length: " + entity.getContentLength());  
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));  
                        String text = "";
                        res.append(text);  
                        while ((text = bufferedReader.readLine()) != null) {  
                            res.append(text);  
                            System.out.println(text);  
                        }  
                         
                    }  
                    EntityUtils.consume(entity);  
                } finally {  
                    response.close();  
                }  
            } finally {  
                httpclient.close();  
            }  
            return  res.toString();  
              
        }  
      
      //企业付款
      @SuppressWarnings("deprecation")
	public static String httpsRequestEnterprise(String requestUrl,  String outputStr) throws Exception {  
            KeyStore keyStore  = KeyStore.getInstance("PKCS12");  
            StringBuilder res = new StringBuilder("");  
            FileInputStream instream = new FileInputStream(new File(Const.getCertPah()));  
            try {  
                keyStore.load(instream, PayCommonUtil.MCH_ID.toCharArray());  
            } finally {  
                instream.close();  
            }  
  
            // Trust own CA and all self-signed certs  
            SSLContext sslcontext = SSLContexts.custom()  
                    .loadKeyMaterial(keyStore, PayCommonUtil.MCH_ID.toCharArray())  
                    .build();  
            // Allow TLSv1 protocol only  
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(  
                    sslcontext,  
                    new String[] { "TLSv1" },  
                    null,  
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);  
            CloseableHttpClient httpclient = HttpClients.custom()  
                    .setSSLSocketFactory(sslsf)  
                    .build();  
            try {  
  
                HttpPost httpost = new HttpPost(requestUrl);  
//                httpost.addHeader("Connection", "keep-alive");  
//                httpost.addHeader("Accept", "*/*");  
//                httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");  
//                httpost.addHeader("Host", "api.mch.weixin.qq.com");  
//                httpost.addHeader("X-Requested-With", "XMLHttpRequest");  
//                httpost.addHeader("Cache-Control", "max-age=0");  
//                httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");  
                 StringEntity entity2 = new StringEntity(outputStr ,Consts.UTF_8);  
                 httpost.setEntity(entity2);  
                System.out.println("executing request" + httpost.getRequestLine());  
  
                CloseableHttpResponse response = httpclient.execute(httpost);  
                 
                try {  
                    HttpEntity entity = response.getEntity();  
                      
                    System.out.println("----------------------------------------");  
                    System.out.println(response.getStatusLine());  
                    if (entity != null) {  
                        System.out.println("Response content length: " + entity.getContentLength());  
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));  
                        String text = "";
                        res.append(text);  
                        while ((text = bufferedReader.readLine()) != null) {  
                            res.append(text);  
                            System.out.println("企业付款返回结果"+text);  
                        }  
                    }  
                    EntityUtils.consume(entity);  
                } finally {  
                    response.close();  
                }  
            } finally {  
                httpclient.close();  
            }  
            return  res.toString();  
              
        } 
      //xml解析  
      @SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map doXMLParse(String strxml) throws JDOMException, IOException {  
            strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");  
  
            if(null == strxml || "".equals(strxml)) {  
                return null;  
            }  
              
            Map m = new HashMap();  
              
            InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));  
            SAXBuilder builder = new SAXBuilder();  
            Document doc = builder.build(in);  
            Element root = doc.getRootElement();  
            List list = root.getChildren();  
            Iterator it = list.iterator();  
            while(it.hasNext()) {  
                Element e = (Element) it.next();  
                String k = e.getName();  
                String v = "";  
                List children = e.getChildren();  
                if(children.isEmpty()) {  
                    v = e.getTextNormalize();  
                } else {  
                    v = getChildrenText(children);  
                }  
                  
                m.put(k, v);  
            }  
              
            //关闭流  
            in.close();  
              
            return m;  
        }  
        
      @SuppressWarnings("rawtypes")
	public static String getChildrenText(List children) {  
            StringBuffer sb = new StringBuffer();  
            if(!children.isEmpty()) {  
                Iterator it = children.iterator();  
                while(it.hasNext()) {  
                    Element e = (Element) it.next();  
                    String name = e.getName();  
                    String value = e.getTextNormalize();  
                    List list = e.getChildren();  
                    sb.append("<" + name + ">");  
                    if(!list.isEmpty()) {  
                        sb.append(getChildrenText(list));  
                    }  
                    sb.append(value);  
                    sb.append("</" + name + ">");  
                }  
            }  
              
            return sb.toString();  
        }
      
      public static String toJson(Object object){
    	  ObjectMapper mapper = new ObjectMapper();
    	  String json = "";
    	  try {
			json = mapper.writeValueAsString(object);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	  return json;
      }
      
      public static void main(String[] args) {
    	  String strxml = "<xml><appid><![CDATA[wx72ef6980bae5da5c]]></appid><bank_type><![CDATA[CFT]]></bank_type><cash_fee><![CDATA[100]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[N]]></is_subscribe><mch_id><![CDATA[1361440702]]></mch_id><nonce_str><![CDATA[UoxmTM4BXANIL4oDmhS9d0lPbAQLQ0Kp]]></nonce_str><openid><![CDATA[ojFD0vypxyvPK63XzT7vTt-XYUyU]]></openid><out_trade_no><![CDATA[00ce06b065404d49929bc367a62c8d47]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[632DE7CBB260EA5D22FC1264D871CCF7]]></sign><time_end><![CDATA[20161126112722]]></time_end><total_fee>100</total_fee><trade_type><![CDATA[APP]]></trade_type><transaction_id><![CDATA[4008732001201611260859823912]]></transaction_id></xml>";
		try {
			System.out.println(toJson(doXMLParse(strxml)));
		} catch (JDOMException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}